<template>


    <el-card class="flex-1">
      <div slot="header">
        <div class="flex-x gap-4 pt-2">
          <span>
            <vxe-input v-model="query.keyword" :placeholder="'搜索素材名称'" size="medium" clearable
              @keyup.enter.native="filterByKeyword"></vxe-input>
          </span>
          <span>
            <el-button type="primary" plain size="small" @click="filterByKeyword" icon="el-icon-search"
              :loading="loading">搜索</el-button>
          </span>
          <span class="flex-1"></span>
          <span>
            <el-button type="primary" size="small" @click="handleAddByUpload" icon="el-icon-upload">
              上传素材
            </el-button>       
            <el-button type="danger" size="small" @click="handleAddByEdit" icon="el-icon-edit">
              编写文档
            </el-button>
            <el-button type="success" size="small" @click="handleAdd" icon="el-icon-plus">
              添加题单
            </el-button>
          </span>
        </div>
      </div>

      <el-tabs v-model="query.stuffType" @tab-click="handleStuffTypeChange">
        <el-tab-pane v-for="(type, index) in stuffTypeList" :key="index" :name="type.value">
          <template #label>
            {{ type.label }}
            <el-badge v-if="countByType(type.value) > 0" :value="countByType(type.value)" class="ml-2" />
          </template>
        </el-tab-pane>
      </el-tabs>

      <!-- Stuff Table -->
      <vxe-table stripe auto-resize :data="stuffList" :loading="loading" :custom-config="tableCustomConfig"
         align="center" ref="table">
        <vxe-table-column field="id" title="ID" width="60"></vxe-table-column>
        <vxe-table-column field="title" title="标题" min-width="120"></vxe-table-column>
        <vxe-table-column field="stuffType" title="类型" width="100"></vxe-table-column>
        <vxe-table-column field="fileUrl" title="文件" min-width="200">
          <template v-slot="{ row }">
            <el-link type="primary" :href="row.fileUrl" target="_blank">{{ row.fileUrl.substring(row.fileUrl.lastIndexOf('/') + 1) }}</el-link>
          </template>
        </vxe-table-column>
        <vxe-table-column field="fileSize" title="文件大小" width="100">
          <template v-slot="{ row }">
            {{ formatFileSize(row.fileSize) }}
          </template>
        </vxe-table-column>
        <vxe-table-column field="gmtCreate" title="创建时间" width="150" :visible="false">
          <template v-slot="{ row }">
            {{ formatDate(row.gmtCreate) }}
          </template>
        </vxe-table-column>
        <vxe-table-column field="gmtModified" title="修改时间" width="150">
          <template v-slot="{ row }">
            {{ formatDate(row.gmtModified) }}
          </template>
        </vxe-table-column>
        <vxe-table-column title="操作" width="100" fixed="right">
          <template v-slot="{ row }">
            <el-tooltip effect="dark" content="编辑" placement="top">
              <el-button plain circle type="primary" size="mini" icon="el-icon-edit" @click="handleEdit(row)">
              </el-button>
            </el-tooltip>
            <el-tooltip effect="dark" content="删除" placement="top">
              <el-button plain circle type="danger" size="mini" icon="el-icon-delete" @click="handleDelete(row)">
              </el-button>
            </el-tooltip>           
          </template>
        </vxe-table-column>
      </vxe-table>

      <!-- Pagination -->
      <div class="flex-x justify-end mt-4 gap-4">
        <el-pagination class="page" @size-change="handleSizeChange" @current-change="handleCurrentChange"
          :current-page="query.currentPage" :page-sizes="[10, 20, 50, 100]" :page-size="query.limit"
          layout="total, sizes, prev, pager, next, jumper" :total="total">
        </el-pagination>
        <el-button type="plain" size="mini" @click="handleTableCustom" circle icon="el-icon-menu"></el-button>
      </div>

      <!-- Stuff Dialog -->
      <el-dialog :title="dialogTitle" :visible.sync="dialogVisible" width="520px" @close="resetForm" destroy-on-close>
        <el-alert v-if="stuffForm.showUpload" type="info" class="mb-4">
          您可以选择上传视频、ppt、word、pdf、md等文件，默认使用文件名作为素材标题。
        </el-alert>
        <el-form :model="stuffForm" :rules="rules" ref="stuffForm" label-width="100px">
          <el-form-item label="上级目录" prop="parentId">
            <stuff-dir-select v-model="stuffForm.parentId" />
          </el-form-item>

          <el-form-item label="标题" prop="title">
            <el-input v-model="stuffForm.title"></el-input>
          </el-form-item>     
          
          <el-form-item v-if="stuffForm.showUpload" label="文件" prop="fileUrl">
            <aliyun-oss-upload drag progress :show-file-list="true" accept="*" type="stuff"
              @success="handleUploadSuccess" class="w-full">
              <i class="el-icon-upload"></i>
              <div class="el-upload__text">将文件拖到此处，或 <em>点击上传</em></div>
            </aliyun-oss-upload>
          </el-form-item>
          
        </el-form>
        <div slot="footer" class="dialog-footer">
          <el-button @click="dialogVisible = false">取 消</el-button>
          <el-button type="primary" @click="submitForm">确 定</el-button>
        </div>
      </el-dialog>

      <file-stuff-dialog ref="uploadStuffDialog" @success="handleStuffChanged" />

      <md-stuff-dialog ref="mdStuffDialog" @success="handleStuffChanged" />

      <TagSelect ref="tagSelect" @change="handleTagsChange" />
    </el-card>

</template>

<script>
import api from '@/common/api';
import utils from '@/common/utils';
import { DEFAULT_TABLE_CUSTOM_CONFIG } from "@/common/constants";
import Editor from "@/components/admin/Editor.vue";
import TagSelect from '@/components/admin/TagSelectDialog.vue';
import AliyunOssUpload from '@/components/admin/AliyunOssUpload.vue';
import StuffDirSelect from '@/components/admin/StuffDirSelect.vue';
import { filter } from 'xe-utils';
import FileStuffDialog from './components/FileStuffDialog.vue';
import MdStuffDialog from './components/MdStuffDialog.vue';

export default {
  name: 'CourseList',
  components: {
    Editor,
    TagSelect,
    AliyunOssUpload,
    StuffDirSelect,
    FileStuffDialog,
    MdStuffDialog
  },
  props: {
    parentId: {
      type: Number,
      default: undefined,
    }
  },
  data() {
    return {
      stuffTypeList: [
          { label: '全部', value: 'all' },
          { label: '视频', value: 'video' },
          { label: '音频', value: 'audio' },
          { label: 'PPT', value: 'ppt' },
          { label: 'word文档', value: 'doc' },
          { label: 'PDF文档', value: 'pdf' },
          { label: 'md文档', value: 'md' },
          { label: '图片', value: 'image' },
          { label: '题单', value: 'question_set' },
          { label: '其他', value: 'other' },
      ],
      tableCustomConfig: DEFAULT_TABLE_CUSTOM_CONFIG,
      // List data
      stuffList: [],
      typeCountList: [],
      currentRow: {},
      loading: false,
      total: 0,
      query: {
        parentId: this.parentId,
        viewMode: 'table',
        stuffType: 'all',
        keyword: '',
        currentPage: 1,
        limit: 10
      },

      // Dialog data
      dialogVisible: false,
      dialogTitle: '',
      stuffForm: {
        title: '',
        stuffType: '',
        uid: '',
        gid: '',
        parentId: null,
        fileUrl: '',
        fileSize: 0
      },
      rules: {
        title: [
          { required: true, message: '请输入标题', trigger: 'blur' },
          { min: 2, max: 50, message: '长度在 2 到 50 个字符', trigger: 'blur' }
        ],
        stuffType: [
          { required: true, message: '请输入类型', trigger: 'blur' }
        ],
        fileUrl: [
          { required: true, message: '请上传文件', trigger: 'change' }
        ]
      }
    };
  },
  watch: {
    parentId(newVal) {
      this.query.parentId = newVal;
      this.getTypeCount();
      this.getDataList();
    }
  },  
  created() {
    this.getTypeCount();
    this.getDataList();
  },
  methods: {
    // get type count
    async getTypeCount() {
      const { data } = await api.admin_getStuffTypeStat({
        tagId: this.query.tagId,
        keyword: this.query.keyword,
        parentId: this.query.parentId
      });
      this.typeCountList = data.data;
    },

    // Get data list
    async getDataList() {
      try {
        this.loading = true;
        const params = Object.assign({}, this.query)
        const { data } = await api.admin_getStuffLeafList(params);
        this.stuffList = data.data.records;
        this.total = data.data.total;
        console.log('stuffList', this.stuffList);
      } catch (error) {
        this.$message.error('获取素材列表失败');
      } finally {
        this.loading = false;
      }
    },

    // Handle pagination
    handleSizeChange(val) {
      this.query.limit = val;
      this.getDataList();
    },
    handleCurrentChange(val) {
      this.query.currentPage = val;
      this.getDataList();
    },
    handleTableCustom() {
      this.$refs.table?.openCustom()
    },
    handleStuffTypeChange(tab) {
      this.query.stuffType = tab.name;
      this.getDataList();
    },
    // 编辑标签
    handleEditTags(row) {
      this.currentRow = row
      const tagIds = row.tags?.map(it => it.id)
      this.$refs.tagSelect.open(tagIds)
    },
    async handleTagsChange(tagIds) {
      try {
        const data = {
          targetId: this.currentRow.id,
          targetType: 'stuff',
          tagIds
        }
        await api.admin_saveTagRel(data);
        this.$message.success('标签更新成功');
        this.getDataList();
      } catch (error) {
        this.$message.error('标签更新失败');
      }
    },

    // Handle CRUD operations
    handleAdd() {
      this.dialogTitle = '添加素材';
      this.dialogVisible = true;
      if (this.query.stuffType === 'all') {
        this.stuffForm.stuffType =  'video';
      } else {
        this.stuffForm.stuffType =  this.query.stuffType;
      }
    },
    handleEdit(row) {
      this.dialogTitle = '编辑素材';
      this.stuffForm = { ...row, parentId: row.parentId || 0 };
      if ('md' === row.stuffType.toLowerCase()) {
        this.$refs.mdStuffDialog.open(row)
      } else {
        this.dialogVisible = true;
      }
    },
    
    handleAddByUpload() {      
      this.stuffForm = {stuffType:'', parentId:this.parentId || 0, showUpload:true};   
      const data = Object.assign({}, this.stuffForm);
      this.$refs.uploadStuffDialog.open(data);      
    },

    handleAddByEdit() {
      this.stuffForm.stuffType = 'md';
      this.dialogVisible = true;
    },

    handleStuffChanged(data) {
      if (data && data.stuffType) {
        this.query.stuffType = data.stuffType
      }
      this.getTypeCount();
      this.getDataList();
    },

    async handleDelete(row) {
      try {
        await this.$confirm('确认删除该素材?', '提示', {
          confirmButtonText: '确定',
          cancelButtonText: '取消',
          type: 'warning'
        });
        await api.admin_deleteStuff(row.id);
        this.$message.success('删除成功');
        this.handleStuffChanged();
      } catch (error) {
        if (error !== 'cancel') {
          this.$message.error('删除失败');
        }
      }
    },
    async handleStatusChange(row, field) {
      try {
        await api.admin_saveStuff({
          id: row.id,
          [field]: row[field]
        });
        this.$message.success('状态更新成功');
      } catch (error) {
        row[field] = !row[field];
        this.$message.error('状态更新失败');
      }
    },
    handleUploadSuccess({url, name, file}) {
      const data = {
        fileUrl: url,
        fileSize: file.size,        
      }
      const {type} = file;
      console.log('file', file);
      if (type.startsWith('video')) {
        data.stuffType = 'video';
      } else if (name.includes('pptx') || name.includes('ppt')) {
        data.stuffType = 'ppt';
      } else if (type.includes('msword') || name.includes('doc') || name.includes('docx')) {
        data.stuffType = 'doc';
      } else if (type.includes('pdf') || name.includes('pdf')) {
        data.stuffType = 'pdf';
      } else if (type.startsWith('image')) {
        data.stuffType = 'image';
      } else if (type.includes('md') || name.includes('md')) {
        data.stuffType = 'md';
      } else if (type.startsWith('audio')){
        data.stuffType = 'audio';
      } else {
        data.stuffType = 'other';
      }

      
      if (!this.stuffForm.title) {        
        data.title = name.substring(0, name.lastIndexOf('.'));
      }
      this.stuffForm = Object.assign({}, this.stuffForm, data);
    },

    // Form operations
    submitForm() {
      this.$refs.stuffForm.validate(async (valid) => {
        if (valid) {
          try {
            const data = Object.assign({}, this.stuffForm, {parentId: this.parentId})
            await api.admin_saveStuff(data);
            this.$message.success(this.stuffForm.id ? '更新成功' : '添加成功');
            this.dialogVisible = false;
            this.getDataList();
          } catch (error) {
            this.$message.error(this.stuffForm.id ? '更新失败' : '添加失败');
          }
        }
      });
    },
    resetForm() {
      this.$refs.stuffForm?.resetFields();
      this.stuffForm = {
        title: '',
        stuffType: '',
        uid: '',
        gid: '',
        parentId: null,
        fileUrl: '',
        fileSize: 0
      };
    },

    // Filter operations
    async filterByKeyword() {
      this.query.currentPage = 1;
      this.getTypeCount();
      this.getDataList();
    },

    // Utils
    formatDate(date) {
      return date
    },
    handleManageSections(row) {
      this.$router.push({
        name: 'admin-course-section-list',
        query: { courseId: row.id }
      });
    },

    formatFileSize(size) {
      return utils.formatFileSize(size);
    },

    handleFileUploadSuccess(res) {
      if (res.status === 200) {
        this.stuffForm.fileUrl = res.data.url;
        this.stuffForm.fileSize = res.data.size;
        this.$message.success('上传成功');
      } else {
        this.$message.error('上传失败');
      }
    },

    countByType(type) {
      if (type === 'all') {
        return this.typeCountList.reduce((acc, curr) => acc + curr.count, 0);
      } else {
        const stat = filter(this.typeCountList, it => it.stuffType.toLowerCase() === type.toLowerCase())
        return stat?.[0]?.count || 0;
      }
    },

  }
};
</script>

<style scoped>
.avatar-uploader {
  border: 1px dashed #d9d9d9;
  border-radius: 6px;
  cursor: pointer;
  position: relative;
  overflow: hidden;
  width: 120px;
}

.avatar-uploader:hover {
  border-color: #409EFF;
}

.avatar-uploader-icon {
  font-size: 28px;
  color: #8c939d;
  width: 120px;
  height: 120px;
  line-height: 120px;
  text-align: center;
}

.avatar {
  width: 120px;
  height: 120px;
  display: block;
  object-fit: cover;
}
</style>
